package NG::Sys::Loop::Cgi;
use strict;
use warnings;
use utf8;

use base 'NG::Sys::Loop::Run';

my $cgi;
my $count = 0;
sub on_before_loop {
	my ($self) = @_;
	$self->make_actions;
	$self->warn_to_logger;
	$self->ext_die;
	$self->logger->info("started");

	require CGI;
	unless($self->{can_upload}){
		$CGI::DISABLE_UPLOADS = 1;
	}else{
		$CGI::DISABLE_UPLOADS = 0;
	}
	unless($self->{post_max}){
		$CGI::POST_MAX = 4 * 1042;
	}else{
		$CGI::POST_MAX = $self->{post_max};
	}

	return 1;
}
sub on_enter_loop {
	my ($app) = @_;
	require CGI::Fast;
	$cgi = new CGI::Fast;
}
sub on_init_process {
	my ($app) = @_;
	require NG::Sys::Form;
	my $form = new NG::Sys::Form($app,$cgi);
	$app->drop_context;
	$app->{tmp_log} = "";
	return ($form);
}
#sub on_before_process {
#	my ($app) = @_;
#}
#sub on_after_process {
#	my ($app) = @_;
#}
sub on_done_process {
	my ($app) = @_;
	$app->drop_context;
	$app->{tmp_log} = "";
}
sub on_leave_loop {
	my ($self) = @_;
	$count++;
	if($self->{restart_after} && $self->{restart_after} <= $count){
		return 1;
	}
	return -M $self->fullscript < 0;
}
sub on_after_loop {
	my ($self) = @_;
	$self->logger->info("stopped");
}


sub process_error {
	my ($app,$scope,$error,undef,$form) = @_;
	$app->logger->error("LOOP_ERROR[$scope]: ".$error);
	if($form){
		$form->process($app->template_tt->read("_error"));
	}
}

sub make_actions {
	my ($self) = shift;
	$self->{actions} ||= {};
	my $class = ref $self;
	no strict 'refs';
	for my $pkg(grep {$_->isa('NG::Sys::Hnd')} @{$class."::ISA"}){
		_make_action($self->{actions},$pkg);
		$pkg->_init($self);
	}
	_make_action($self->{actions},"main");
}
sub _make_action {
	my ($h,$pkg) = @_;
	no strict 'refs';
	for(grep { /^cmd_/ and defined &{${$pkg."::"}{$_}} } keys %{$pkg."::"}){
		$h->{$_} = ${$pkg."::"}{$_};
	}
}
sub tmp_log {
	my ($self) = @_;
	if(@_ > 1){
		$self->{tmp_log} .= $_[1]."\n";
	}else{
		return $self->{tmp_log};
	}
}
sub on_process {
	my ($self,$form) = @_;
	my @action = $self->check_action($form,$form->{input}{cmd});
	unless(@action or @action = $self->check_action($form,'default')) {
		$form->set_header(-status => "400 Bad Request");
		print $form->header;
		return 0;
	}else{
		return $self->do_action($form,@action);
	}
}
sub do_action {
	my ($self,$form,$action,$object) = @_;
	if(ref $action){
		$action = "cmd_".join("_",@$action);
	}elsif(!$action){
		$action = "cmd_default";
	}
	if (my $func = $self->{actions}{$action}){
		return $func->($self,$form,$object);
	}
	return 0;
}
sub check_action {
	my ($self, $form, $cmd) = @_;
	$cmd ||= "";

	my ($mode,$object,$action) = split /\./,$cmd;
	unless($mode){
		return;
	}
	my $key = "cmd_".$mode;
	if($object){
		unless($action){
			$action = $object;
			$object = undef;
		}
		$key .= "_".$action;
	}
	
	if(my $func = $self->{actions}{$key}){
		return ($key,$object);
	}
	return;
}

1;
